import React, {
  ReactNode,
  useState,
  useEffect,
  useCallback,
  forwardRef,
  useImperativeHandle,
  useRef,
} from 'react';
import ReactDOM from 'react-dom';
import { Message } from '@/design';
import { isEmpty } from '@/utils/common';
import styles from './Modal.less';

interface ModalProps {
  content?: string | ReactNode; //提示的内容
  visible?: boolean;
  title?: string | ReactNode; //title
  onClose: Function;
  type?: 'alert' | 'prompt' | 'confirm';
  inputDefaultValue?: string; //prompt类型时候的默认值
  placeholder?: string;
  onSure?: Function;
  onCancel?: Function;
  text?: string; // alert时候按钮的字
  afterClose?: Function;
}

const Modal: React.FunctionComponent<ModalProps> = props => {
  const [value, setValue] = useState<string>('');
  const inputEl = useCallback(node => {
    if (node !== null) {
      setValue(node.value);
    }
  }, []);

  const { onCancel, onSure } = props;

  const isPrompt = props.type === 'prompt';
  const isAlert = props.type === 'alert';
  const isChoose = isPrompt || props.type === 'confirm';

  const result = (
    <>
      <div
        className={`
        ${styles.modal_mask}
        ${props.visible ? '' : styles.hide}`}
      ></div>
      <div className={`${styles.modal} ${props.visible ? '' : styles.hide}`}>
        <div className={styles.modal_inner}>
          {/* header */}
          <header className={styles.modal_header}>
            <div className={styles.modal_header_title}>
              {props.title || '提示'}
            </div>
          </header>

          {/* main */}
          <main className={styles.modal_main}>
            {isPrompt ? (
              <TextInput
                ref={inputEl}
                inputDefaultValue={props.inputDefaultValue}
                placeholder={props.placeholder}
              ></TextInput>
            ) : (
              props.children
            )}
          </main>

          {/* footer */}
          <footer className={styles.modal_footer}>
            {isChoose && (
              <>
                <button
                  type="button"
                  className={styles.button}
                  onClick={() => {
                    onCancel && onCancel();
                  }}
                >
                  取消
                </button>
                <button
                  type="button"
                  className={styles.button}
                  onClick={() => {
                    onSure && onSure(value);
                  }}
                >
                  確定
                </button>
              </>
            )}
            {isAlert && (
              <button
                type="button"
                className={styles.button}
                onClick={() => {
                  onCancel && onCancel();
                }}
              >
                {props.text || '知道了'}
              </button>
            )}
          </footer>
        </div>
      </div>
    </>
  );
  return ReactDOM.createPortal(result, document.body);
};

interface ITextInput {
  inputDefaultValue?: string;
  placeholder?: string;
}

// 輸入框組件
const TextInput = forwardRef(
  ({ inputDefaultValue, placeholder }: ITextInput, ref) => {
    const [value, setValue] = useState<string>(inputDefaultValue || '');
    const inputRef: any = useRef<HTMLInputElement>(null);

    useEffect(() => {
      inputRef.current.focus();
      window.scrollTo(0, 130);
    }, []);

    useImperativeHandle(ref, () => ({
      value: inputRef.current.value,
    }));

    return (
      <input
        ref={inputRef}
        className={styles.input}
        value={value}
        onChange={e => {
          setValue(e.target.value);
        }}
        placeholder={placeholder}
      ></input>
    );
  },
);

const modal = ({
  content,
  afterClose,
  title,
  text,
  inputDefaultValue,
  placeholder,
  type,
  onCancel,
  onSure,
}: ModalProps) => {
  const close = () => {
    ReactDOM.render(React.cloneElement(component, { visible: false }), div);
    setTimeout(() => {
      ReactDOM.unmountComponentAtNode(div);
      div.remove();
    }, 300);
  };
  const component = (
    <Modal
      visible={true}
      onClose={() => {
        close();
        afterClose && afterClose();
      }}
      title={title}
      type={type}
      inputDefaultValue={inputDefaultValue}
      placeholder={placeholder}
      onSure={onSure}
      onCancel={onCancel}
      text={text}
    >
      {content}
    </Modal>
  );
  const div = document.createElement('div');
  document.body.append(div);
  ReactDOM.render(component, div);
  return close;
};

// alert 类型
const alert = ({ content, text }: IChooseModal) => {
  const onCancel = () => {
    close();
  };

  const close = modal({
    content,
    text,
    type: 'alert',
    onCancel,
    onClose: () => {},
  });
};

// 可选择类型
const confirm = ({ content, yes, afterClose, title }: IChooseModal) => {
  const onSure = () => {
    let res: any = yes && yes();
    if (isEmpty(res) && res.then) {
      res.then(close).catch((err: any) => {
        Message.warn({ content: err });
      });
    } else {
      close();
    }
  };

  const onCancel = () => {
    close();
    afterClose && afterClose();
  };
  const close = modal({
    content,
    afterClose,
    title,
    onSure,
    onCancel,
    type: 'confirm',
    onClose: () => {},
  });
};

interface IChooseModal {
  title?: string | ReactNode;
  content?: string | ReactNode;
  yes?: Function | ((value?: string) => void);
  no?: Function | (() => void);
  text?: string;
  afterClose?: () => void;
  type?: string;
  inputDefaultValue?: string;
  placeholder?: string;
  onSure?: Function;
  onCancel?: Function;
}

// 输入的类型
const prompt = ({
  inputDefaultValue,
  yes,
  afterClose,
  title,
  placeholder,
  content,
}: IChooseModal) => {
  const onSure = (value: string) => {
    let res: any = yes && yes(value);
    if (isEmpty(res) && res.then) {
      res.then(close).catch((err: any) => {
        Message.warn({ content: err });
      });
    } else {
      close();
    }
  };

  const onCancel = () => {
    close();
    afterClose && afterClose();
  };

  const close = modal({
    content,
    title,
    type: 'prompt',
    inputDefaultValue,
    placeholder,
    onSure,
    onCancel,
    onClose: () => {},
  });
};

export default {
  alert,
  confirm,
  prompt,
};
